package br.com.firula.web.filter;

import java.io.IOException;
import java.text.DecimalFormat;
import java.util.Date;
import java.util.Enumeration;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import br.com.firula.bo.LogBO;
import br.com.firula.to.LogTO;
import br.com.firula.to.UsuarioTO;

public class LogFilter implements Filter {

	private LogBO mgrLog = null;

	public void destroy() {
		System.out.println("Log Filter destroyed");
	}

	public void init(FilterConfig filterConfig) throws ServletException {
		try {
			WebApplicationContext  wac = WebApplicationContextUtils.getWebApplicationContext(filterConfig.getServletContext());
			mgrLog = (LogBO)wac.getBean("logBO");
		} catch(Exception ignoredForNow) {
			ignoredForNow.printStackTrace();
		}
	}

	@SuppressWarnings("unchecked")
	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
		String caminho = ((HttpServletRequest) req).getServletPath();
		try {
			HttpServletRequest request = ((HttpServletRequest) req);
			HttpServletResponse response = ((HttpServletResponse) res);

			Date entradaRequisicao = new Date();
			long inicio = System.currentTimeMillis();
			Cookie[] cookies = request.getCookies();
			Cookie visit = null;
			Boolean newVisit = Boolean.FALSE;
			Cookie uniqueVisit = null;
			Boolean newUniqueVisit = Boolean.FALSE;

			if (cookies != null) {
				for (Cookie cookie : cookies) {
					String name = cookie.getName();
					if (name.equals("decV")) {
						visit = cookie;
					} else if (name.equals("decUV")) {
						uniqueVisit = cookie;
					}
				}
			}
			if (visit == null) {
				visit = new Cookie("decV", new DecimalFormat("00000000000000").format(Math.random() * 10000000000000l));
				visit.setMaxAge(-1);
				newVisit = Boolean.TRUE;
				response.addCookie(visit);
			}
			if (uniqueVisit == null) {
				uniqueVisit = new Cookie("decUV", new DecimalFormat("00000000000000").format(Math.random() * 10000000000000l));
				newUniqueVisit = Boolean.TRUE;
				uniqueVisit.setMaxAge(365 * 24 * 60 * 60);
				response.addCookie(uniqueVisit);
			}

			LogTO log = new LogTO();
			log.setDataCriacao(entradaRequisicao);
			log.setAction(request.getServletPath());
			log.setIp(request.getRemoteHost());
			log.setUrl(request.getRequestURL().toString());
			log.setUri(request.getRequestURI());
			log.setCookieVisit(visit.getValue());
			log.setCookieVisitMaxAge(Long.valueOf(visit.getMaxAge()));
			log.setCookieUniqueVisit(uniqueVisit.getValue());
			log.setCookieUniqueVisitMaxAge(Long.valueOf(uniqueVisit.getMaxAge()));
			log.setCookieVisitNew(newVisit);
			log.setCookieUniqueVisitNew(newUniqueVisit);
			log.setReferer(request.getHeader("referer"));
			log.setUserAgent(request.getHeader("user-agent"));

			String parametros = "";
			Enumeration hds = request.getParameterNames();
			while (hds.hasMoreElements()) {
				String hd = (String) hds.nextElement();
				String value = request.getParameter(hd);
				parametros = parametros.concat(hd + "=" + (StringUtils.isAsciiPrintable(value)?value:"NOT LATIN1-CONVERSIBLE") + "&");

			}
			log.setParam(parametros);

			// Obtem informacoes relacionadas a sessao apenas se a resposta nao foi commitada, ou se a sessao ja foi criada
			if (!response.isCommitted() || request.getSession(false) != null) {
				log.setSessionId(request.getSession().getId());

				if (request.getSession().getAttribute("USUARIO") != null) {
					log.setIdUsuario(((UsuarioTO) request.getSession().getAttribute("USUARIO")).getId().longValue());
				}
			}

			try {
				mgrLog.save(log);
			} catch (Exception e) {
				System.out.println("PERDEU UM LOG: POSSIVELMENTE POR CONTA DE PROBLEMAS COM UTF8, MOTIVO DE TER COLOCADO ESTE TRY");
				e.printStackTrace();
			}
			chain.doFilter(req, res);

			double time = ((double) (System.currentTimeMillis() - inicio));

			log.setTimeInMillis(time);
			mgrLog.save(log);

		} catch (Exception e) {
			System.out.println("ERRO NO LOG FILTER:  caiu no catch\nData: "+new Date()+" Req: "+caminho+" ");
			e.printStackTrace();
		}
		return;
	}
}